Conversation
…ofiling disabled tag: no release note tag: ai generated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BenchmarksStartupParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 60 metrics, 11 unstable metrics. Startup time reports for insecure-bankgantt
title insecure-bank - global startup overhead: candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.061 s) : 0, 1060608
Total [baseline] (8.799 s) : 0, 8798735
Agent [candidate] (1.055 s) : 0, 1054694
Total [candidate] (8.818 s) : 0, 8818099
section iast
Agent [baseline] (1.219 s) : 0, 1219402
Total [baseline] (9.539 s) : 0, 9539204
Agent [candidate] (1.225 s) : 0, 1225316
Total [candidate] (9.568 s) : 0, 9567635
gantt
title insecure-bank - break down per module: candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section tracing
crashtracking [baseline] (1.226 ms) : 0, 1226
crashtracking [candidate] (1.213 ms) : 0, 1213
BytebuddyAgent [baseline] (635.924 ms) : 0, 635924
BytebuddyAgent [candidate] (630.936 ms) : 0, 630936
AgentMeter [baseline] (29.688 ms) : 0, 29688
AgentMeter [candidate] (29.421 ms) : 0, 29421
GlobalTracer [baseline] (249.498 ms) : 0, 249498
GlobalTracer [candidate] (248.587 ms) : 0, 248587
AppSec [baseline] (31.986 ms) : 0, 31986
AppSec [candidate] (32.025 ms) : 0, 32025
Debugger [baseline] (59.166 ms) : 0, 59166
Debugger [candidate] (59.064 ms) : 0, 59064
Remote Config [baseline] (591.177 µs) : 0, 591
Remote Config [candidate] (597.373 µs) : 0, 597
Telemetry [baseline] (8.026 ms) : 0, 8026
Telemetry [candidate] (8.02 ms) : 0, 8020
Flare Poller [baseline] (8.342 ms) : 0, 8342
Flare Poller [candidate] (8.872 ms) : 0, 8872
section iast
crashtracking [baseline] (1.223 ms) : 0, 1223
crashtracking [candidate] (1.217 ms) : 0, 1217
BytebuddyAgent [baseline] (798.31 ms) : 0, 798310
BytebuddyAgent [candidate] (801.109 ms) : 0, 801109
AgentMeter [baseline] (11.328 ms) : 0, 11328
AgentMeter [candidate] (11.417 ms) : 0, 11417
GlobalTracer [baseline] (238.338 ms) : 0, 238338
GlobalTracer [candidate] (240.242 ms) : 0, 240242
IAST [baseline] (25.743 ms) : 0, 25743
IAST [candidate] (26.74 ms) : 0, 26740
AppSec [baseline] (31.617 ms) : 0, 31617
AppSec [candidate] (31.098 ms) : 0, 31098
Debugger [baseline] (59.227 ms) : 0, 59227
Debugger [candidate] (59.646 ms) : 0, 59646
Remote Config [baseline] (524.429 µs) : 0, 524
Remote Config [candidate] (554.939 µs) : 0, 555
Telemetry [baseline] (12.86 ms) : 0, 12860
Telemetry [candidate] (13.19 ms) : 0, 13190
Flare Poller [baseline] (3.443 ms) : 0, 3443
Flare Poller [candidate] (3.497 ms) : 0, 3497
Startup time reports for petclinicgantt
title petclinic - global startup overhead: candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.061 s) : 0, 1061397
Total [baseline] (11.169 s) : 0, 11169072
Agent [candidate] (1.063 s) : 0, 1063299
Total [candidate] (11.15 s) : 0, 11150327
section appsec
Agent [baseline] (1.249 s) : 0, 1248814
Total [baseline] (11.06 s) : 0, 11060276
Agent [candidate] (1.244 s) : 0, 1244102
Total [candidate] (11.077 s) : 0, 11077257
section iast
Agent [baseline] (1.23 s) : 0, 1230441
Total [baseline] (11.163 s) : 0, 11162502
Agent [candidate] (1.222 s) : 0, 1222167
Total [candidate] (11.308 s) : 0, 11307860
section profiling
Agent [baseline] (1.183 s) : 0, 1182792
Total [baseline] (11.131 s) : 0, 11130907
Agent [candidate] (1.183 s) : 0, 1183306
Total [candidate] (11.024 s) : 0, 11023906
gantt
title petclinic - break down per module: candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section tracing
crashtracking [baseline] (1.241 ms) : 0, 1241
crashtracking [candidate] (1.221 ms) : 0, 1221
BytebuddyAgent [baseline] (636.356 ms) : 0, 636356
BytebuddyAgent [candidate] (635.762 ms) : 0, 635762
AgentMeter [baseline] (29.669 ms) : 0, 29669
AgentMeter [candidate] (29.54 ms) : 0, 29540
GlobalTracer [baseline] (250.785 ms) : 0, 250785
GlobalTracer [candidate] (249.611 ms) : 0, 249611
AppSec [baseline] (32.33 ms) : 0, 32330
AppSec [candidate] (32.138 ms) : 0, 32138
Debugger [baseline] (60.302 ms) : 0, 60302
Debugger [candidate] (60.235 ms) : 0, 60235
Remote Config [baseline] (598.322 µs) : 0, 598
Remote Config [candidate] (613.537 µs) : 0, 614
Telemetry [baseline] (8.187 ms) : 0, 8187
Telemetry [candidate] (8.119 ms) : 0, 8119
Flare Poller [baseline] (5.774 ms) : 0, 5774
Flare Poller [candidate] (9.839 ms) : 0, 9839
section appsec
crashtracking [baseline] (1.22 ms) : 0, 1220
crashtracking [candidate] (1.209 ms) : 0, 1209
BytebuddyAgent [baseline] (662.279 ms) : 0, 662279
BytebuddyAgent [candidate] (659.714 ms) : 0, 659714
AgentMeter [baseline] (12.096 ms) : 0, 12096
AgentMeter [candidate] (11.985 ms) : 0, 11985
GlobalTracer [baseline] (249.081 ms) : 0, 249081
GlobalTracer [candidate] (248.311 ms) : 0, 248311
IAST [baseline] (24.599 ms) : 0, 24599
IAST [candidate] (24.511 ms) : 0, 24511
AppSec [baseline] (184.492 ms) : 0, 184492
AppSec [candidate] (184.043 ms) : 0, 184043
Debugger [baseline] (65.847 ms) : 0, 65847
Debugger [candidate] (65.409 ms) : 0, 65409
Remote Config [baseline] (600.86 µs) : 0, 601
Remote Config [candidate] (594.881 µs) : 0, 595
Telemetry [baseline] (8.581 ms) : 0, 8581
Telemetry [candidate] (8.543 ms) : 0, 8543
Flare Poller [baseline] (3.55 ms) : 0, 3550
Flare Poller [candidate] (3.562 ms) : 0, 3562
section iast
crashtracking [baseline] (1.246 ms) : 0, 1246
crashtracking [candidate] (1.206 ms) : 0, 1206
BytebuddyAgent [baseline] (807.007 ms) : 0, 807007
BytebuddyAgent [candidate] (800.374 ms) : 0, 800374
AgentMeter [baseline] (11.446 ms) : 0, 11446
AgentMeter [candidate] (11.365 ms) : 0, 11365
GlobalTracer [baseline] (239.346 ms) : 0, 239346
GlobalTracer [candidate] (238.684 ms) : 0, 238684
IAST [baseline] (25.756 ms) : 0, 25756
IAST [candidate] (26.562 ms) : 0, 26562
AppSec [baseline] (32.508 ms) : 0, 32508
AppSec [candidate] (32.549 ms) : 0, 32549
Debugger [baseline] (60.534 ms) : 0, 60534
Debugger [candidate] (57.386 ms) : 0, 57386
Remote Config [baseline] (529.017 µs) : 0, 529
Remote Config [candidate] (517.148 µs) : 0, 517
Telemetry [baseline] (12.081 ms) : 0, 12081
Telemetry [candidate] (13.534 ms) : 0, 13534
Flare Poller [baseline] (3.456 ms) : 0, 3456
Flare Poller [candidate] (3.541 ms) : 0, 3541
section profiling
crashtracking [baseline] (1.182 ms) : 0, 1182
crashtracking [candidate] (1.181 ms) : 0, 1181
BytebuddyAgent [baseline] (690.398 ms) : 0, 690398
BytebuddyAgent [candidate] (690.825 ms) : 0, 690825
AgentMeter [baseline] (9.13 ms) : 0, 9130
AgentMeter [candidate] (9.127 ms) : 0, 9126
GlobalTracer [baseline] (207.27 ms) : 0, 207270
GlobalTracer [candidate] (207.091 ms) : 0, 207091
AppSec [baseline] (32.445 ms) : 0, 32445
AppSec [candidate] (32.528 ms) : 0, 32528
Debugger [baseline] (65.658 ms) : 0, 65658
Debugger [candidate] (65.278 ms) : 0, 65278
Remote Config [baseline] (574.352 µs) : 0, 574
Remote Config [candidate] (568.519 µs) : 0, 569
Telemetry [baseline] (7.805 ms) : 0, 7805
Telemetry [candidate] (7.877 ms) : 0, 7877
Flare Poller [baseline] (3.525 ms) : 0, 3525
Flare Poller [candidate] (3.564 ms) : 0, 3564
ProfilingAgent [baseline] (93.567 ms) : 0, 93567
ProfilingAgent [candidate] (93.969 ms) : 0, 93969
Profiling [baseline] (94.128 ms) : 0, 94128
Profiling [candidate] (94.545 ms) : 0, 94545
LoadParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 19 metrics, 17 unstable metrics. Request duration reports for petclinicgantt
title petclinic - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section baseline
no_agent (19.47 ms) : 19270, 19670
. : milestone, 19470,
appsec (18.704 ms) : 18517, 18891
. : milestone, 18704,
code_origins (17.578 ms) : 17406, 17749
. : milestone, 17578,
iast (17.802 ms) : 17627, 17977
. : milestone, 17802,
profiling (18.237 ms) : 18055, 18419
. : milestone, 18237,
tracing (17.945 ms) : 17767, 18123
. : milestone, 17945,
section candidate
no_agent (18.348 ms) : 18158, 18538
. : milestone, 18348,
appsec (18.617 ms) : 18430, 18804
. : milestone, 18617,
code_origins (17.74 ms) : 17568, 17913
. : milestone, 17740,
iast (17.705 ms) : 17529, 17880
. : milestone, 17705,
profiling (18.208 ms) : 18024, 18392
. : milestone, 18208,
tracing (17.858 ms) : 17684, 18032
. : milestone, 17858,
Request duration reports for insecure-bankgantt
title insecure-bank - request duration [CI 0.99] : candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section baseline
no_agent (1.222 ms) : 1211, 1233
. : milestone, 1222,
iast (3.177 ms) : 3135, 3219
. : milestone, 3177,
iast_FULL (5.761 ms) : 5703, 5818
. : milestone, 5761,
iast_GLOBAL (3.73 ms) : 3657, 3802
. : milestone, 3730,
profiling (2.129 ms) : 2110, 2149
. : milestone, 2129,
tracing (1.893 ms) : 1877, 1909
. : milestone, 1893,
section candidate
no_agent (1.237 ms) : 1225, 1249
. : milestone, 1237,
iast (3.287 ms) : 3240, 3334
. : milestone, 3287,
iast_FULL (5.894 ms) : 5835, 5953
. : milestone, 5894,
iast_GLOBAL (3.628 ms) : 3565, 3690
. : milestone, 3628,
profiling (2.143 ms) : 2124, 2162
. : milestone, 2143,
tracing (1.939 ms) : 1922, 1957
. : milestone, 1939,
DacapoParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 11 metrics, 1 unstable metrics. Execution time for biojavagantt
title biojava - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section baseline
no_agent (14.99 s) : 14990000, 14990000
. : milestone, 14990000,
appsec (14.731 s) : 14731000, 14731000
. : milestone, 14731000,
iast (18.404 s) : 18404000, 18404000
. : milestone, 18404000,
iast_GLOBAL (18.19 s) : 18190000, 18190000
. : milestone, 18190000,
profiling (14.972 s) : 14972000, 14972000
. : milestone, 14972000,
tracing (15.034 s) : 15034000, 15034000
. : milestone, 15034000,
section candidate
no_agent (15.752 s) : 15752000, 15752000
. : milestone, 15752000,
appsec (14.828 s) : 14828000, 14828000
. : milestone, 14828000,
iast (18.291 s) : 18291000, 18291000
. : milestone, 18291000,
iast_GLOBAL (18.181 s) : 18181000, 18181000
. : milestone, 18181000,
profiling (15.074 s) : 15074000, 15074000
. : milestone, 15074000,
tracing (14.886 s) : 14886000, 14886000
. : milestone, 14886000,
Execution time for tomcatgantt
title tomcat - execution time [CI 0.99] : candidate=1.62.0-SNAPSHOT~f21e7d43dc, baseline=1.62.0-SNAPSHOT~742623564b
dateFormat X
axisFormat %s
section baseline
no_agent (1.483 ms) : 1471, 1494
. : milestone, 1483,
appsec (2.536 ms) : 2481, 2591
. : milestone, 2536,
iast (2.27 ms) : 2200, 2340
. : milestone, 2270,
iast_GLOBAL (2.314 ms) : 2244, 2384
. : milestone, 2314,
profiling (2.098 ms) : 2043, 2153
. : milestone, 2098,
tracing (2.082 ms) : 2028, 2136
. : milestone, 2082,
section candidate
no_agent (1.481 ms) : 1470, 1493
. : milestone, 1481,
appsec (3.808 ms) : 3584, 4032
. : milestone, 3808,
iast (2.268 ms) : 2198, 2337
. : milestone, 2268,
iast_GLOBAL (2.312 ms) : 2242, 2382
. : milestone, 2312,
profiling (2.094 ms) : 2039, 2150
. : milestone, 2094,
tracing (2.075 ms) : 2021, 2128
. : milestone, 2075,
|
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| listener.afterScopeClosed(); | ||
| } catch (Exception e) { | ||
| ContinuableScopeManager.log.debug("ScopeListener threw exception in close()", e); | ||
| if (!scopeManager.scopeListeners.isEmpty()) { |
There was a problem hiding this comment.
I think this change makes sense. Although in my experience usually the Iterator gets stack allocated by the JIT, so I'm not sure the provided explanation makes sense here.
That said, we'd have to look at an allocation profile to know for certain.
There was a problem hiding this comment.
Dug into this and the more accurate explanation is
It avoids the iteration dispatch path entirely, whether or not the JIT scalar-replaces the iterator, the
isEmpty()check is fewer instructions and method calls than entering and immediately exiting the for-each loop.
dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java
Outdated
Show resolved
Hide resolved
dd-trace-core/src/main/java/datadog/trace/core/scopemanager/ContinuableScope.java
Outdated
Show resolved
Hide resolved
dougqh
left a comment
There was a problem hiding this comment.
Some minor suggestions on further improvements
I'd also like Stuart to review, since he's more familiar with this code
…e reads Addresses review feedback from dougqh: the JIT will be conservative with volatile reads from CopyOnWriteArrayList.isEmpty() and won't hoist them, so we cache in locals ourselves. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
In Spring Petclinic throughput tests... Prior to the isEmpty being pulled into a local variable, this change was negative by 2-5% / 500-1000 requests/sec. After pulling isEmpty into a local variable, this change is mostly neutral throughput wise. Overall, this change seems good to me. Unfortunately, we just don't have a lot of easy big wins anymore. |
What Does This Do
Reduces overhead in the scope activation/close hot path by:
isEmpty()early exits inContinuableScope.onProperClose()andafterActivated()to skip iteration when no listeners are registered, with results cached in local variables to avoid redundant volatile readsscopeState == Stateful.DEFAULTidentity check inbeforeActivated()to skipAgentSpan.fromContext()and virtual dispatch when profiling is disabledprofilingEnabledandhasDepthLimitboolean flags inContinuableScopeManagerto skip per-activationAgentSpan.fromContext(),instanceof, andscopeStack.depth()callsMotivation
Scope activation and close happen on every instrumented method entry/exit. In the default configuration (no profiling, no scope listeners, no depth limit), these methods were doing unnecessary work on every call:
CopyOnWriteArrayLists (the loop body is never entered, but the iteration overhead remains)AgentSpan.fromContext()andinstanceof ProfilerContextincreateScopeState()only to returnStateful.DEFAULTscopeStack.depth()to compare againstInteger.MAX_VALUEWhy this is faster
CopyOnWriteArrayList.isEmpty()is O(1) — it reads the internal array length without entering the iteration path. The results are cached in local boolean variables since the JIT will be conservative with volatile reads from CopyOnWriteArrayList and won't hoist them across uses. The cached boolean flags (profilingEnabled,hasDepthLimit) turn per-invocation virtual dispatch and method calls into simple branch predictions.Scope listeners are registered once at startup, not concurrently with scope operations, so the widened
isEmpty()race window inonProperClose()is not reachable in practice.Benchmark results (8 threads, JDK 21, macOS aarch64, Fork=1, Warmup=2, Measurement=3)
activateAndClosenestedActivateAndCloseactivateSameSpanactiveSpanLookupHuman readability score: 9/10
All changes follow existing codebase patterns (boolean flag caching, isEmpty guards).
Additional Notes
Also adds
ScopeLifecycleBenchmark.javaJMH benchmark covering scope activate/close, re-activation, nested scopes, and active span lookup.tag: no release note
tag: ai generated
Contributor Checklist
type:andcomp:labelssolvesinstead🤖 Generated with Claude Code